package org.iabako.server.serviceimpl.business;

import org.iabako.server.dao.JpaDAO;
import org.iabako.server.dao.business.ProductDAO;
import org.iabako.server.dao.business.QueryDefinitionDAO;
import org.iabako.shared.dto.SuggestItemDTO;
import org.iabako.shared.entity.business.AbstractEntity;
import org.iabako.shared.entity.business.Product;
import org.iabako.shared.entity.enumeration.TrackingType;
import org.iabako.shared.entity.user.Enterprise;
import org.iabako.shared.exception.IabakoActionForbiddenException;
import org.iabako.shared.exception.IabakoUniqueConstraintException;
import org.iabako.shared.iservice.business.ProductService;
import org.iabako.shared.iservice.business.TrackingService;
import org.iabako.shared.querydefinition.SearchMotorQueryEnum;
import org.iabako.shared.querydefinition.columndefinition.ColumnDefinition;
import org.iabako.shared.querydefinition.columndefinition.ProductColumnEnum;
import org.iabako.shared.querydefinition.dto.QueryDefinitionDTO;
import org.iabako.shared.querydefinition.dto.QueryOperatorEnum;
import org.iabako.shared.tools.GenericTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by jose on 16/01/15.
 */

@org.springframework.stereotype.Service("productService")
public class ProductServiceImpl extends AbstractServiceImpl implements ProductService {


    @Autowired
    private ProductDAO productDAO;
    @Autowired
    private QueryDefinitionDAO queryDefinitionDAO;
    @Autowired
    private TrackingService trackingService;

    @Override
    protected JpaDAO getDAO() {
        return productDAO;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Product save(Product product) throws IabakoActionForbiddenException, IabakoUniqueConstraintException {
        Enterprise enterprise = getEnterpriseFromSessionUser();

        if (enterprise != null && enterprise.isDemo()) {
            throw new IabakoActionForbiddenException("action_forbidden_for_demo_title", "action_forbidden_for_demo_text", true);
        }

        if (product.getEnterprise() == null) {
            if (product.getId() != null && enterprise.getAllRelatedEnterprises().size() > 1) {
                //Do not change Enterprise!
                product.setEnterprise(productDAO.findById(product.getId()).getEnterprise());
            } else {
                product.setEnterprise(enterprise);
            }
        }

        if (!getDAO().isUniqueNumber(product)) {
            throw new IabakoUniqueConstraintException(
                    messages.getLabel("validation_product_unique_constraint_error_title"),
                    messages.getLabel("validation_product_unique_constraint_error_text", product.getNumber()), true, true);
        }

        setBusinessTrackInfo(product);

        if (product.getId() == null) {
            trackingService.addTrackingToUserSession(TrackingType.productNew, product);
        } else {
            trackingService.addTrackingToUserSession(TrackingType.productModify, product);
        }

        return (Product) super.save(product);
    }

    public List<Product> getProducts() {
        return productDAO.getProducts();
    }

    //Used for demo
    public Product getByNumber(Enterprise enterprise, String number) {
        return productDAO.getByNumber(enterprise, number);
    }

    public QueryDefinitionDTO getSearchQueryDefinitionDTO(QueryDefinitionDTO qd) {
        qd.setSearchMotorQuery(SearchMotorQueryEnum.ProductSearch);
        qd.addCriteria(ProductColumnEnum.productEnterprise, QueryOperatorEnum.IN, (ArrayList) getSessionUser().getEnterprise().getVisibleEnterprises());
        queryDefinitionDAO.executeQueryDefinition(qd);
        return qd;
    }

    public QueryDefinitionDTO setSearchCriteriaFromSuggest(QueryDefinitionDTO qd, Long hiddenSelectionCode, String suggestionValue) {
        if (!GenericTools.isEmpty(hiddenSelectionCode)) {
            qd.addCriteria(ProductColumnEnum.productId, QueryOperatorEnum.EQUALS, hiddenSelectionCode);
            return qd;
        }
        return setSearchCriteriaFromSuggest(qd,
                suggestionValue,
                new ColumnDefinition[]{ProductColumnEnum.number, ProductColumnEnum.name});
    }

    public List<SuggestItemDTO> getSuggestions(String req) {
        List<SuggestItemDTO> suggestions = new ArrayList<SuggestItemDTO>(10);

        List<Object[]> results = productDAO.getNamesBySuggestion(req);
        for (Object[] result : results) {
            suggestions.add(new SuggestItemDTO(result[0] + "", (String) result[1], (String) result[2], null, null));
        }

        return suggestions;
    }

    public AbstractEntity getByHiddenSelectionCode(String hiddenSelectionCode) {
        return getById(Long.parseLong(hiddenSelectionCode));
    }

    public Double getLastTax() {
        return productDAO.getLastTax();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean remove(Long id) {
        trackingService.addTrackingToUserSession(TrackingType.productDelete, (Product) getById(id));
        productDAO.deleteAttachedObjects(id);
        return super.remove(id);
    }
}
